/**
* Copyright 2014-2017 yangming.liu<bytefox@126.com>.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*/
package org.bytesoft.bytetcc.supports.springcloud.serialize;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.jms.XAConnectionFactory;
import javax.jms.XASession;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.xa.XAResource;
import org.bytesoft.bytejta.supports.jdbc.DataSourceHolder;
import org.bytesoft.bytejta.supports.jdbc.RecoveredResource;
import org.bytesoft.bytejta.supports.resource.CommonResourceDescriptor;
import org.bytesoft.bytejta.supports.resource.LocalXAResourceDescriptor;
import org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;
import org.bytesoft.bytejta.supports.wire.RemoteCoordinator;
import org.bytesoft.bytejta.supports.wire.RemoteCoordinatorRegistry;
import org.bytesoft.bytetcc.supports.springcloud.SpringCloudCoordinator;
import org.bytesoft.transaction.supports.resource.XAResourceDescriptor;
import org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class XAResourceDeserializerImpl implements XAResourceDeserializer, ApplicationContextAware {
static final Logger logger = LoggerFactory.getLogger(XAResourceDeserializerImpl.class);
static Pattern pattern = Pattern.compile("^[^:]+\\s*:\\s*[^:]+\\s*:\\s*\\d+$");
private ApplicationContext applicationContext;
private Map<String, XAResourceDescriptor> cachedResourceMap = new ConcurrentHashMap<String, XAResourceDescriptor>();
public XAResourceDescriptor deserialize(String identifier) {
try {
Object bean = this.applicationContext.getBean(identifier);
XAResourceDescriptor cachedResource = this.cachedResourceMap.get(identifier);
if (cachedResource == null) {
cachedResource = this.deserializeResource(identifier, bean);
if (cachedResource != null) {
this.cachedResourceMap.put(identifier, cachedResource);
}
}
return cachedResource;
} catch (BeansException bex) {
Matcher matcher = pattern.matcher(identifier);
if (matcher.find() == false) {
logger.error("can not find a matching xa-resource(identifier= {})!", identifier);
return null;
}
RemoteCoordinatorRegistry registry = RemoteCoordinatorRegistry.getInstance();
RemoteCoordinator coordinator = registry.getTransactionManagerStub(identifier);
if (coordinator == null) {
SpringCloudCoordinator springCloudCoordinator = new SpringCloudCoordinator();
springCloudCoordinator.setIdentifier(identifier);
coordinator = (RemoteCoordinator) Proxy.newProxyInstance(SpringCloudCoordinator.class.getClassLoader(),
new Class[] { RemoteCoordinator.class }, springCloudCoordinator);
registry.putTransactionManagerStub(identifier, coordinator);
}
RemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();
descriptor.setIdentifier(identifier);
descriptor.setDelegate(registry.getTransactionManagerStub(identifier));
return descriptor;
} catch (Exception ex) {
logger.error("can not find a matching xa-resource(identifier= {})!", identifier);
return null;
}
}
private XAResourceDescriptor deserializeResource(String identifier, Object bean) throws Exception {
if (DataSourceHolder.class.isInstance(bean)) {
DataSourceHolder holder = (DataSourceHolder) bean;
RecoveredResource xares = new RecoveredResource();
xares.setDataSource(holder.getDataSource());
LocalXAResourceDescriptor descriptor = new LocalXAResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
return descriptor;
} else if (javax.sql.DataSource.class.isInstance(bean)) {
javax.sql.DataSource dataSource = (javax.sql.DataSource) bean;
RecoveredResource xares = new RecoveredResource();
xares.setDataSource(dataSource);
LocalXAResourceDescriptor descriptor = new LocalXAResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
return descriptor;
} else if (XADataSource.class.isInstance(bean)) {
XADataSource xaDataSource = (XADataSource) bean;
XAConnection xaConnection = xaDataSource.getXAConnection();
java.sql.Connection connection = null;
try {
connection = xaConnection.getConnection();
XAResource xares = xaConnection.getXAResource();
CommonResourceDescriptor descriptor = new CommonResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
descriptor.setManaged(xaConnection);
return descriptor;
} catch (Exception ex) {
logger.warn(ex.getMessage());
XAResource xares = xaConnection.getXAResource();
CommonResourceDescriptor descriptor = new CommonResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
descriptor.setManaged(xaConnection);
return descriptor;
} finally {
this.closeQuietly(connection);
}
} else if (XAConnectionFactory.class.isInstance(bean)) {
XAConnectionFactory connectionFactory = (XAConnectionFactory) bean;
javax.jms.XAConnection xaConnection = connectionFactory.createXAConnection();
XASession xaSession = xaConnection.createXASession();
javax.jms.Session session = null;
try {
session = xaSession.getSession();
XAResource xares = xaSession.getXAResource();
CommonResourceDescriptor descriptor = new CommonResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
descriptor.setManaged(xaConnection);
return descriptor;
} catch (Exception ex) {
logger.warn(ex.getMessage());
XAResource xares = xaSession.getXAResource();
CommonResourceDescriptor descriptor = new CommonResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
descriptor.setManaged(xaConnection);
return descriptor;
} finally {
this.closeQuietly(session);
}
} else if (ManagedConnectionFactory.class.isInstance(bean)) {
ManagedConnectionFactory connectionFactory = (ManagedConnectionFactory) bean;
ManagedConnection managedConnection = connectionFactory.createManagedConnection(null, null);
javax.resource.cci.Connection connection = null;
try {
connection = (javax.resource.cci.Connection) managedConnection.getConnection(null, null);
XAResource xares = managedConnection.getXAResource();
CommonResourceDescriptor descriptor = new CommonResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
descriptor.setManaged(managedConnection);
return descriptor;
} catch (Exception ex) {
logger.warn(ex.getMessage());
XAResource xares = managedConnection.getXAResource();
CommonResourceDescriptor descriptor = new CommonResourceDescriptor();
descriptor.setDelegate(xares);
descriptor.setIdentifier(identifier);
descriptor.setManaged(managedConnection);
return descriptor;
} finally {
this.closeQuietly(connection);
}
} else {
return null;
}
}
protected void closeQuietly(javax.resource.cci.Connection closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception ex) {
logger.debug(ex.getMessage());
}
}
}
protected void closeQuietly(java.sql.Connection closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception ex) {
logger.debug(ex.getMessage());
}
}
}
protected void closeQuietly(javax.jms.Session closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception ex) {
logger.debug(ex.getMessage());
}
}
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}